package com.flexrrb.controls
{
	import com.flexrrb.events.NoteEvent;
	import com.flexrrb.managers.MovableManager;
	import com.flexrrb.skin.EmptySkin;
	
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.ui.Keyboard;
	
	import mx.binding.utils.BindingUtils;
	import mx.containers.Canvas;
	import mx.controls.Image;
	import mx.controls.TextInput;
	import mx.core.EdgeMetrics;
	import mx.effects.Fade;
	import mx.events.EffectEvent;
	import mx.styles.CSSStyleDeclaration;
	import mx.styles.StyleManager;
	
	[Event(name="noteRemove", type="com.flexrrb.events.NoteEvent")]
	
	public class StickyNote extends Canvas
	{
		[DefaultProperty("textNote")]
		
		private var _textField:TextInput;
		private var _textNote:String;
		
		private var _movable:Boolean;
		private var _startPoint:Point;
		
		private var _closeBtn:Image;
		private var _editBtn:Image;
		
		private var _invalidateMovable:Boolean;
		private var _invalidateCloseButton:Boolean;
		private var _movableManager:MovableManager;
		
		private var _body:Canvas;
		private var _edge:EdgeMetrics;
		private var _measured:Boolean;
		
		private var _closeButtonEffect:Fade;
		private static var classConstructed:Boolean = constructClass();
		
		[Embed("../../../assets/delete.png")]
		private static var closeBtnImg:Class;
		
		[Embed("../../../assets/edit.png")]
		private static var editBtnImg:Class;
		
		[Embed("../../../assets/stickyNote.png")]
		private static var stickyNoteImg:Class;
		
		private static function constructClass():Boolean
		{
			var selector:CSSStyleDeclaration = StyleManager.getStyleDeclaration("StickyNote");
			if(!selector)
			{
				selector = new CSSStyleDeclaration();
			}
			
			selector.defaultFactory = function():void
			{
				this.backgroundColor="";
				this.noteBackgroundColor="0xFCD116";
				this.paddingLeft = "5";
				this.paddingRight = "5";
				this.paddingTop = "5";
				this.paddingBottom = "5";
				this.buttonImage = closeBtnImg;
				this.editButtonImage = editBtnImg;
				this.contentBackgroundImage = stickyNoteImg;
			}
			
			StyleManager.setStyleDeclaration("StickyNote", selector, false);
			return true;
		}
		
		public function StickyNote()
		{
			super();
			
			_closeButtonEffect = new Fade();
			_closeButtonEffect.duration = 500;
			
			_edge = new EdgeMetrics();
			_movableManager = new MovableManager();
			_movableManager.register(this);
		}
		
		[Bindable("noteChanged")]
		public function get textNote():String
		{
			return _textNote;
		}
		
		public function set textNote(value:String):void
		{
			_textNote = value;
			dispatchEvent(new NoteEvent(NoteEvent.NOTE_CHANGED, _textNote));
		}
		
		public function get movable():Boolean
		{
			return _movable;
		}
		
		public function set movable(value:Boolean):void
		{
			_movable = value;
			if(_movable)
				_movableManager.enableMove();
			else
				_movableManager.disableMove();
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			_edge.left = this.getStyle("paddingLeft") as Number;
			_edge.right = this.getStyle("paddingRight") as Number;
			_edge.top = this.getStyle("paddingTop") as Number;
			_edge.bottom = this.getStyle("paddingBottom") as Number;
			
			//width and height specified
			if(!_measured)
			{
				this._body.width = this.getExplicitOrMeasuredWidth() - 
											(this._closeBtn.getExplicitOrMeasuredWidth() * 0.5);
				this._body.height = this.getExplicitOrMeasuredHeight() - (this._closeBtn.height * 0.5);
			}
			else //width and height not specified
			{
				//make it a square
				this._body.width = this._textField.getExplicitOrMeasuredWidth();
				this._body.height = this._textField.getExplicitOrMeasuredWidth();
			}
			
			//this._textField.width = this._body.getExplicitOrMeasuredWidth();
			this._textField.height = this._editBtn.y - this._closeBtn.getExplicitOrMeasuredHeight() * 0.5;
			this._textField.y = this._closeBtn.getExplicitOrMeasuredHeight() * 0.5;
			
			this._body.move((this._closeBtn.getExplicitOrMeasuredWidth() * 0.5), (this._closeBtn.getExplicitOrMeasuredHeight() * 0.5));
		}
		
		override protected function measure():void
		{
			super.measure();
			this.width = (this._closeBtn.getExplicitOrMeasuredWidth() * 0.5) + this._body.getExplicitOrMeasuredWidth;
			this.height = (this._closeBtn.getExplicitOrMeasuredHeight() * 0.5) + this._body.getExplicitOrMeasuredHeight + this._editBtn.getExplicitOrMeasuredHeight();
				
			_measured = true;
		}
		
		override protected function createChildren():void
		{
			super.createChildren();
			
			_body = new Canvas();
			
			var bgImg:Object = this.getStyle("contentBackgroundImage");
			if(!bgImg)
				_body.setStyle("backgroundColor",this.getStyle("noteBackgroundColor"));
			else
				_body.setStyle("backgroundImage", bgImg);
			
			_textField = new TextInput();
			_textField.enabled = false;
			_textField.percentWidth = 95;
			_textField.setStyle("horizontalCenter", 0);
			_textField.setStyle("backgroundAlpha", 0);
			_textField.setStyle("borderAlpha", 0);
			_textField.setStyle("borderSkin", EmptySkin);
			_textField.setStyle("focusSkin", EmptySkin);
			_textField.setStyle("disabledColor", 0x000000);
			BindingUtils.bindProperty(_textField, "text", this, "textNote");
			
			addEditButton();
			addCloseButton();
			
			addChild(_body);
			_body.addChild(_editBtn);
			_body.addChild(_textField);
			
			addChild(_closeBtn);
		}
		
		private function onEditClick(event:MouseEvent):void
		{
			_closeBtn.alpha = 0;
			_closeBtn.visible = true;
			
			_closeButtonEffect.target = _closeBtn;
			_closeButtonEffect.alphaFrom = 0;
			_closeButtonEffect.alphaTo = 1;
			_closeButtonEffect.play();
			
			_textField.enabled = true;
			_textField.setFocus();
			
			_movableManager.disableMove();
			_textField.addEventListener(KeyboardEvent.KEY_UP, onKeyUp, false, 0, true);
		}
		
		private function onKeyUp(event:KeyboardEvent):void
		{
			if(event.keyCode != Keyboard.ESCAPE)
				return;
			
			_textField.enabled = false;
			_closeButtonEffect.target = _closeBtn;
			_closeButtonEffect.alphaFrom = 1;
			_closeButtonEffect.alphaTo = 0;
			_closeButtonEffect.addEventListener(EffectEvent.EFFECT_END, onEffectEnd, false, 0, true);
			_closeButtonEffect.play();
			
			this.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			
			_movableManager.enableMove();
		}
		
		private function onEffectEnd(event:EffectEvent):void
		{
			_closeBtn.visible = false;
			_closeButtonEffect.removeEventListener(EffectEvent.EFFECT_END, onEffectEnd);
		}
		
		private function onCloseBtnClick(event:MouseEvent):void
		{
			dispatchEvent(new NoteEvent(NoteEvent.NOTE_REMOVE));
		}
		
		private function addEditButton():void
		{
			_editBtn = new Image();
			_editBtn.source = this.getStyle("editButtonImage");
			_editBtn.useHandCursor = true;
			_editBtn.buttonMode = true;
			_editBtn.setStyle("right", 5);
			_editBtn.setStyle("bottom", 5);
			_editBtn.addEventListener(MouseEvent.CLICK, onEditClick, false, 0, true);
		}
		
		private function addCloseButton():void
		{
			_closeBtn = new Image();
			_closeBtn.source = this.getStyle("buttonImage");
			_closeBtn.useHandCursor = true;
			_closeBtn.buttonMode = true;
			_closeBtn.visible = false;
			
			_closeBtn.addEventListener(MouseEvent.CLICK, onCloseBtnClick, false, 0, true);
		}
	}
}